home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1991-05-01 | 57.9 KB | 1,989 lines | [ TEXT/MPS ]
// UWindow.cp // Copyright © 1987-1991 by Apple Computer Inc. All rights reserved. #ifndef __UWINDOW__ #include <UWindow.h> #endif #ifndef __UGEOMETRY__ #include <UGeometry.h> #endif #ifndef __ULIST__ #include <UList.h> #endif #ifndef __UADORNERS__ #include <UAdorners.h> #endif #ifndef __EDITIONS__ #include <Editions.h> #endif #ifndef __DIALOGS__ #include <Dialogs.h> #endif #ifndef __UAPPLICATION__ #include <UApplication.h> #endif #ifndef __UDOCUMENT__ #include <UDocument.h> #endif #ifndef __UPRINTHANDLER__ #include <UPrintHandler.h> #endif #ifndef __OSUTILS__ #include <OSUtils.h> #endif #ifndef __UMACAPPUTILITIES__ #include <UMacAppUtilities.h> #endif #ifndef __UFAILURE__ #include <UFailure.h> #endif #ifndef __UPATCH__ #include <UPatch.h> #endif #ifndef __UMACAPPGLOBALS__ #include <UMacAppGlobals.h> #endif #ifndef __ERRORS__ #include <Errors.h> #endif #ifndef __SYSEQU__ #include <SysEqu.h> #endif #ifndef __TRAPS__ #include <Traps.h> #endif #ifndef __DEVICES__ #include <Devices.h> #endif #ifndef __ULOMEM__ #include <ULoMem.h> #endif #ifndef __MENUS__ #include <Menus.h> #endif #ifndef __UMENUMGR__ #include <UMenuMgr.h> #endif #ifndef __FIXMATH__ #include <FixMath.h> #endif #ifndef __TOOLUTILS__ #include <ToolUtils.h> #endif #ifndef __RESOURCES__ #include <Resources.h> #endif //-------------------------------------------------------------------------------------------------- Rect gStdWMoveBounds; Rect gStdWSizeRect; Rect gStdWScreenRect; short gStdStaggerCount = 0; //-------------------------------------------------------------------------------------------------- #pragma segment MAClose pascal void TCloseWindowCommand::DoIt(void) { if (fView) ((TWindow *)fView)->CloseByUser(); } //-------------------------------------------------------------------------------------------------- #pragma segment MASelCommand pascal void TCloseWindowCommand::ICloseWindowCommand(CmdNumber itsCmdNumber, TWindow* itsWindow) { this->INoChangesCommand(itsCmdNumber, NULL, itsWindow); } //-------------------------------------------------------------------------------------------------- #pragma segment MAFields pascal void TCloseWindowCommand::Fields(TObject* obj)// override { obj->DoToField("TCloseWindowCommand", NULL, bClass); inherited::Fields(obj); } //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen pascal void TWindow::Initialize(void) // override { inherited::Initialize(); fAdapted = FALSE; // Set by AdaptToScreen fClosesDocument = TRUE; fConstTitle = 0; //!!! constant? fContDifference = gZeroPt; fContRgnInset = gZeroPt; fDismissed = FALSE; fDisposeOnFree = TRUE; fDoFirstClick = FALSE; fFloats = FALSE; fForcedOnScreen = FALSE; // Set by ForceOnScreen fFreeOnClosing = FALSE; fHideOnSuspend = FALSE; fHorzCentered = FALSE; // Set by Center fIsActive = FALSE; fIsClosable = TRUE; fIsModal = FALSE; fIsResizable = TRUE; fMoveBounds = gStdWMoveBounds; // We can't tell if any changing will be required so we just set these false here. // If the developer sets them true then we respect them or if the developer calls the //corresponding functions we set them. fMustAdapt = FALSE; fMustForceOnScreen = FALSE; fMustHorzCenter = FALSE; fMustStagger = FALSE; fMustVertCenter = FALSE; fOpenInitially = TRUE; fPreDocname = 0; //!!! contstant? fProcID = 0; //!!! contstant? fResizeLimits = gStdWSizeRect; fStaggered = FALSE; // Set by SimpleStagger fTarget = this; fTargetID = fIdentifier; fUpdating = FALSE; fVertCentered = FALSE; // Set by Center fWasHiddenOnSuspend = FALSE; fWMgrWindow = NULL; fGenerateActivates = TRUE; } //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen pascal void TWindow::IWindow(TDocument* itsDocument, WindowPtr itsWMgrWindow, Boolean canResize, Boolean canClose, Boolean disposeOnFree) { short preDocname; short constTitle; Str255 aString; FailInfo fi; Point itsLocation; VPoint itsSize; VOLATILE(itsWMgrWindow); VOLATILE(disposeOnFree); if (fi.Try()) { SetPort(itsWMgrWindow); // So LocalToGlobal works Rect & thePortRect = itsWMgrWindow->portRect;// WITH itsWMgrWindow->portRect) { itsLocation = thePortRect[topLeft]; LocalToGlobal(itsLocation); itsSize = VPoint(thePortRect.Length(vSel), thePortRect.Length(hSel)); } this->IView(itsDocument, NULL, itsLocation, itsSize, sizeVariable, sizeVariable); /* Initialize instance variables -- NOTE that we do this AFTER the call to IView (which eventually triggers a call to Initialize in which intance variables are initialized) */ fWMgrWindow = itsWMgrWindow; itsWMgrWindow = NULL; // so our failure handler works fDisposeOnFree = disposeOnFree; fProcID = GetWindowVariant(fWMgrWindow); SetWRefCon(fWMgrWindow, ((long)this)); fIsResizable = canResize; if (canResize) this->AddAdorner(gResizeIconAdorner, kLowestAdornPriority, FALSE); fIsClosable = canClose; this->BuildWindowRgns(this->BuildWindowRgns(kBuild));// sets fContRgnInset && fContDifference this->SetResizeLimits(gStdWSizeRect[topLeft], gStdWSizeRect[botRight]); this->GetTitle(aString); if (ParseTitleTemplate(aString, preDocname, constTitle)) SetWTitle(fWMgrWindow, aString); fPreDocname = preDocname; fConstTitle = constTitle; this->InstallDocument(itsDocument); this->AddAdorner(gEraseAdorner, kHighestAdornPriority, FALSE); fi.Success(); } else // Recover { if (itsWMgrWindow) itsWMgrWindow = FreeIfWMgrWindow(itsWMgrWindow, disposeOnFree); this->Free(); fi.ReSignal(); } } //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen pascal void TWindow::IRes(TDocument* itsDocument, TView* itsSuperView, Ptr& itsParams) { WindowPtr aWMgrWindow; short preDocname; short constTitle; Str255 aString; FailInfo fi; WindowPtr behind; inherited::IRes(itsDocument, itsSuperView, itsParams); VRect bounds(fLocation, fLocation + fSize); WindowTemplate & templateData = *((WindowTemplatePtr)itsParams);// WITH { if (fi.Try()) { fProcID = templateData.procID; if (templateData.isModal) behind = (WindowPtr) - 1; else behind = this->GetBehindWindowPtr(); if (qNeedsColorQD || gConfiguration.hasColorQD) aWMgrWindow = (WindowPtr)NewCWindow(NULL, bounds, templateData.title, FALSE, templateData.procID, behind, templateData.hasGoAway, ((long)this)); else aWMgrWindow = NewWindow(NULL, bounds, templateData.title, FALSE, templateData.procID, behind, templateData.hasGoAway, ((long)this)); fWMgrWindow = aWMgrWindow; fIsResizable = templateData.resizable; if (templateData.resizable) this->AddAdorner(gResizeIconAdorner, kLowestAdornPriority, FALSE); fIsClosable = templateData.hasGoAway; fTargetID = templateData.targetID; fIsModal = templateData.isModal; fDoFirstClick = templateData.doFirstClick; fFreeOnClosing = templateData.freeOnClosing; fDisposeOnFree = templateData.disposeOnFree; fClosesDocument = templateData.closesDocument; fOpenInitially = templateData.openInitially; this->SetResizeLimits(gStdWSizeRect[topLeft], gStdWSizeRect[botRight]); this->BuildWindowRgns(this->BuildWindowRgns(kBuild));// sets fContRgnInset && fContDifference this->GetTitle(aString); if (ParseTitleTemplate(aString, preDocname, constTitle)) SetWTitle(fWMgrWindow, aString); fPreDocname = preDocname; fConstTitle = constTitle; this->InstallDocument(itsDocument); this->AddAdorner(gEraseAdorner, kHighestAdornPriority, FALSE); fi.Success(); } else // Recover { this->Free(); fi.ReSignal(); } fMustAdapt = templateData.mustAdaptToScreen; fMustHorzCenter = templateData.horzCenter; fMustVertCenter = templateData.vertCenter; fMustStagger = templateData.stagger; fMustForceOnScreen = templateData.mustForceOnScreen; OffsetPtrWStr(itsParams, sizeof(WindowTemplate)); } } //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen pascal WindowPtr TWindow::GetBehindWindowPtr(void) { WindowPtr behind = GetLastFloatingWindowPtr(); if (!behind) behind = (WindowPtr)(-1); // bring the window up in front of all other // windows return behind; } //-------------------------------------------------------------------------------------------------- #pragma segment MAWriteRes pascal void TWindow::WRes(ViewRsrcHandle theResource, Ptr& itsParams) // override { Str255 theTitle; inherited::WRes(theResource, itsParams); this->GetTitle(theTitle); { WindowTemplate & templateData = *((WindowTemplate *)ExpandPtrWStr((Handle)theResource, itsParams, sizeof(WindowTemplate), theTitle.Length())); templateData.procID = fProcID; templateData.hasGoAway = fIsClosable; templateData.resizable = fIsResizable; templateData.isModal = fIsModal; templateData.doFirstClick = fDoFirstClick; templateData.freeOnClosing = fFreeOnClosing; templateData.disposeOnFree = fDisposeOnFree; templateData.closesDocument = fClosesDocument; templateData.openInitially = fOpenInitially; templateData.mustAdaptToScreen = fMustAdapt; templateData.stagger = fMustStagger; templateData.mustForceOnScreen = fMustForceOnScreen; templateData.vertCenter = fMustVertCenter; templateData.horzCenter = fMustHorzCenter; templateData.targetID = fTargetID; templateData.title = theTitle; } } //-------------------------------------------------------------------------------------------------- #pragma segment MAWriteRes pascal void TWindow::WriteRes(ViewRsrcHandle theResource, Ptr& itsParams) // override { gWResSignature = 'wind'; gWResType = "TWindow"; this->WRes(theResource, itsParams); } //-------------------------------------------------------------------------------------------------- #pragma segment MAClose pascal void TWindow::Free(void) // override { Boolean disposeOnFree = fDisposeOnFree;; WindowPtr wmgrWindow = fWMgrWindow; fWMgrWindow = NULL; // ??? will this help? if (fDocument) fDocument->DeleteWindow(this); else gApplication->DeleteFreeWindow(this); inherited::Free(); // ****** DON'T REFER TO ANY FIELDS || METHODS OF this ****** wmgrWindow = FreeIfWMgrWindow(wmgrWindow, disposeOnFree); } //-------------------------------------------------------------------------------------------------- #pragma segment MAActivate pascal void TWindow::Activate(Boolean entering) { HiliteWindow(fWMgrWindow, entering); // make the window "look" active Boolean different = (entering != this->IsActive()); if (different) { inherited::Activate(entering); fIsActive = entering; if (!(fFloats && (fTarget == this))) if (entering) { gApplication->SetTarget(fTarget); } else { gApplication->SetTarget(gApplication); } } } //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen pascal void TWindow::AdaptToScreen(void) { const short stdHScreen = 512; const short stdVScreen = 342; Point diff; VRect theFrame; VPoint newSize; Rect theLimits; fAdapted = TRUE; // We adapted to the screen // Compute pixel difference between current screen and std Mac screen { // !!! Calculation written as two separate expressions so that Point's "-" operator can be inline. Point screenBitsDiff(qd.screenBits.bounds[botRight] - qd.screenBits.bounds[topLeft]); diff = screenBitsDiff - Point(stdVScreen, stdHScreen); } this->GetFrame(theFrame); // If screen is larger, enlarge the window. If the window is too large, shrink it if ((diff != gZeroPt) || (theFrame.bottom > qd.screenBits.bounds.bottom) || (theFrame.right > qd.screenBits.bounds.right))// do an adjustment for larger screen { // the window adapted to the new screen size by proportion. newSize.h = Fix2Long(FixMul(Long2Fix(fSize.h), FixDiv(Long2Fix(stdHScreen + diff.h), Long2Fix(stdHScreen)))); newSize.v = Fix2Long(FixMul(Long2Fix(fSize.v), FixDiv(Long2Fix(stdVScreen + diff.v), Long2Fix(stdVScreen)))); // Consider the location of the window, bound it by the resize limits newSize.ConstrainTo(fResizeLimits); this->Resize(newSize, kInvalidate); } } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean TWindow::AllowsMenuAccess(void) { // Default is to always allow menu access, even if modal return TRUE; } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal Handle GetAndLoadWDefProc(Handle windowDefProc) // utility routine: given a windowDefProc, this routine returns its actual address and loads it { Handle wDefProc = (Handle)(StripLong(windowDefProc));// strip the variant code if ((*wDefProc)) // if Master Ptr is NULL => resource is purged return wDefProc; else { LoadResource(wDefProc); if (ResError() == noErr) // only return it if the LoadResource worked return wDefProc; else return NULL; } } //-------------------------------------------------------------------------------------------------- pascal long CallWDefProc(short varCode, WindowPtr theWindow, short message, long param, Handle wDefProc) = { 0x205F,// MOVE.L (A7)+,A0 0x2050,// MOVE.L (A0),A0 0x4E90// JSR (A0) }; //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen pascal void TWindow::Center(Boolean horizontally, Boolean vertically, Boolean forDialog) { Point windowSize; Point screenSize; Point contentSize; VRect theFrame; Rect screenRect; Boolean rgnsWereBuilt; fHorzCentered = horizontally; fVertCentered = vertically; if ((fWMgrWindow) && (horizontally || vertically)) { this->GetMaxIntersectedDevice(screenRect); screenSize.h = screenRect.Length(hSel); screenSize.v = screenRect.Length(vSel);/* NOTE: GetMaxIntersectedDevice accounts for menubar so don't subtract GetMBarHeight */ rgnsWereBuilt = this->BuildWindowRgns(kBuild); { Rect & strucBounds = (*(((WindowPeek)fWMgrWindow)->strucRgn))->rgnBBox;// WITH windowSize = Point(strucBounds.Length(vSel), strucBounds.Length(hSel)); } this->BuildWindowRgns(rgnsWereBuilt); this->GetFrame(theFrame); contentSize = Point((short)theFrame.Length(vSel), (short) theFrame.Length(hSel)); // The top-left content inset isn't enough; factor in the amount to the right of the // content also. { // Write this calculation as two so that CFront won't inline Point's "-" operator. Point windowInset(windowSize - contentSize); Point bottomRightInset(windowInset - fContRgnInset); fContRgnInset -= bottomRightInset; } if (horizontally) theFrame.left = (screenSize.h - contentSize.h + fContRgnInset.h) / 2; if (vertically) if (forDialog) // Put it in the top third of the screen theFrame.top = ((screenSize.v - contentSize.v + fContRgnInset.v) / 3) + 20; else theFrame.top = ((screenSize.v - contentSize.v + fContRgnInset.v) / 2) + 20; this->Locate(theFrame[topLeft], kDontInvalidate); } } //-------------------------------------------------------------------------------------------------- #pragma segment MAClose pascal void TWindow::Close(void) // override { inherited::Close(); this->Show(FALSE, kRedraw); if (fFreeOnClosing) this->Free(); } //-------------------------------------------------------------------------------------------------- #pragma segment MAClose pascal void TWindow::CloseByUser(void) { if (fDocument) // free window fDocument->CloseView(this); else this->Close(); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::DoKeyCommand(TToolboxEvent* event)// override { inherited::DoKeyCommand(event); } //-------------------------------------------------------------------------------------------------- #pragma segment MASelCommand pascal void TWindow::DoMenuCommand(CmdNumber aCmdNumber)// override { switch (aCmdNumber) { case cClose: Boolean oldObjectPerm; oldObjectPerm = AllocateObjectsFromPerm(FALSE);// Guarantee the allocation TCloseWindowCommand * aCloseWindowCommand = new TCloseWindowCommand; AllocateObjectsFromPerm(oldObjectPerm); aCloseWindowCommand->ICloseWindowCommand(aCmdNumber, this); this->PostCommand(aCloseWindowCommand); break; default: inherited::DoMenuCommand(aCmdNumber); break; } } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::DoSetupMenus(void) // override { if (!fIsModal) // Don't enable menu/app commands if modal { Enable(cClose, fIsClosable); // window objects take care of themselves! inherited::DoSetupMenus(); } } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean TWindow::HandlesCursor(void) // override { return (fHandlesCursor && (this->IsActive() || fDoFirstClick)); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean TWindow::LetsSubViewsHandleCursor(void)// override { return (fLetsSubViewsHandleCursor && (this->IsActive() || fDoFirstClick)); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean TWindow::HandlesHelp(void) // override { return (fHandlesHelp && this->IsActive()); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean TWindow::LetsSubViewsHandleHelp(void)// override { return (fLetsSubViewsHandleHelp && this->IsActive()); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::DrawResizeIcon(void) { if (fIsResizable && this->Focus()) { Rect r; this->GetQDExtent(r); r[topLeft] = r[botRight] - Point(kSBarSizeMinus1, kSBarSizeMinus1); // clip down and avoid drawing the lines that delimit scroll bars #if qDebug UseTempRgn("TWindow::DrawResizeIcon"); #endif #if qDebug UseTempRgn2("TWindow::DrawResizeIcon"); #endif // Avoid drawing the GrowIcon if it would have been clipped GetClip(gTempRgn); RectRgn(gTempRgn2, r); SectRgn(gTempRgn2, gTempRgn, gTempRgn2); if (!EmptyRgn(gTempRgn2)) { SetClip(gTempRgn2); PenNormal(); DrawGrowIcon(fWMgrWindow); SetClip(gTempRgn); } #if qDebug DoneWithTempRgn2(); #endif #if qDebug DoneWithTempRgn(); #endif } } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean TWindow::Focus(void) // override { if (this->IsFocused()) // Already focused { #if qDebug GrafPtr currentPort; GetPort(currentPort); if (this->GetGrafPort() != currentPort) ProgramBreak("TWindow.Focus: Port is incorrect"); #endif } else if (fWMgrWindow) // do my own focus { // Set the port GrafPtr currentPort; GrafPtr theWindowPort = this->GetGrafPort(); GetPort(currentPort); if (currentPort != theWindowPort) SetPort(theWindowPort); SetOrigin(fQDOrigin.h, fQDOrigin.v); gFocusedView = this; // Add the clipping. Clip either to the visrgn or the update region depending on whether // there is an invalid area. RgnHandle theUpdateRgn = ((WindowPeek)fWMgrWindow)->updateRgn; if (!EmptyRgn(theUpdateRgn)) { // The update region is in global coords but the clip is in local coords. // Offset the region to make it in local coords here and restore it there // to save copying it SuperToLocalRgn(theUpdateRgn); #if qDebug UseTempRgn("TWindow::Focus"); #endif if (fUpdating) // clip TO the update region SectRgn(theWindowPort->visRgn, theUpdateRgn, gTempRgn); else // clip OUT the update region DiffRgn(theWindowPort->visRgn, theUpdateRgn, gTempRgn); SetClip(gTempRgn); #if qDebug DoneWithTempRgn(); #endif LocalToSuperRgn(theUpdateRgn); } else SetClip(theWindowPort->visRgn); } else return FALSE; return TRUE; } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean TWindow::FocusOnSuperView(void) // override { return FALSE; } //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen //!!! Former nested routine, now a private method pascal void TWindow::GetLocationAdjustment(Point& delta) { const short kMinDragArea = 4; //!!! Put this in the header Rect visScreenRect; VRect theVFrame; this->GetFrame(theVFrame); Rect theFrame(theVFrame); /* since we don't _really_ know what the drag rgn is, we'll assume that moving the topleft pt of the window on screen is sufficient to make it draggable, so calculate the deltas necessary to move the topleft pt into visible screen rect */ this->GetMaxIntersectedDevice(visScreenRect);// NOTE: uses gTempRgn visScreenRect.Inset(Point(kMinDragArea, kMinDragArea)); if (theFrame.top < visScreenRect.top) delta.v = visScreenRect.top - theFrame.top + fContRgnInset.v; else if (theFrame.top > visScreenRect.bottom) delta.v = visScreenRect.bottom - theFrame.top - fContRgnInset.v; if (theFrame.left < visScreenRect.left) delta.h = visScreenRect.left - theFrame.left + fContRgnInset.h; else if (theFrame.left > theFrame.right) delta.h = visScreenRect.right - theFrame.right - fContRgnInset.h; } pascal void TWindow::ForceOnScreen(void) /* ForceOnScreen guarantees that some minimal drag area is accessible to the user, to be dragged to the desired location. */ { const short kMinDragArea = 4; // ??? should this be settable? fForcedOnScreen = TRUE; /* On many systems (including Color QD && the Radius FPD), it's possible to have a non-rectangular desktop. Try to be nice to people who saved windows on secondary screens. GrayRgn is the true indicator of the shape of the desktop--screenBits.bounds is the size of the screen with the menu bar on it. */ #if qDebug UseTempRgn("ForceOnScreen"); #endif Boolean rgnsWereBuilt = this->BuildWindowRgns(kBuild); WindowRecord & theWindowRecord = *((WindowPeek)fWMgrWindow); { DiffRgn(theWindowRecord.strucRgn, theWindowRecord.contRgn, gTempRgn);/* strucRgn less contRgn ≈≈ drag rgn */ if (EmptyRgn(gTempRgn)) CopyRgn(theWindowRecord.strucRgn, gTempRgn);// at least get the strucRgn } this->BuildWindowRgns(rgnsWereBuilt); // get the desktop rgn, inset by a minimal drag area RgnHandle aTempRgn = MakeNewRgn(); CopyRgn(GetGrayRgn(), aTempRgn); // aTempRgn = desktop rgn InsetRgn(aTempRgn, kMinDragArea, kMinDragArea);// inset aTempRgn SectRgn(gTempRgn, aTempRgn, aTempRgn); // do drag rgn && desktop rgn instersect ? #if qDebug DoneWithTempRgn(); // (GetLocationAdjustment needs gTempRgn) #endif Point delta(gZeroPt); if (EmptyRgn(aTempRgn) ||!IsDraggable((*aTempRgn)->rgnBBox)) this->GetLocationAdjustment(delta);// no => adjust the window's location DisposeRgn(aTempRgn); this->Locate(Point(fLocation) + delta, kDontInvalidate); } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal GDHandle TWindow::GetMaxIntersectedDevice(Rect& screenRect) { if (qNeedsColorQD || gConfiguration.hasColorQD)//!!! Formerly a nested routine { GDHandle aGDHandle; GDHandle maxSectGD; Rect globalStrucRect; Rect aGDScreenRect; Rect gdSectRect; Rect dontCare; long sectArea; long maxSectArea; Rect moveBounds; Boolean rgnsWereBuilt; rgnsWereBuilt = this->BuildWindowRgns(kBuild);/* sets fContRgnInset && fContDifference, and make sure contrgn and strucrgn are available */ globalStrucRect = (*(((WindowPeek)fWMgrWindow)->strucRgn))->rgnBBox; this->BuildWindowRgns(rgnsWereBuilt); moveBounds = fMoveBounds; aGDHandle = GetDeviceList(); maxSectGD = GetMainDevice(); // set as best choice default maxSectArea = 0; while (aGDHandle) { /* calc which scrn intersects largest part of window */ aGDScreenRect = (*aGDHandle)->gdRect; if (SectRect(aGDScreenRect, moveBounds, dontCare) && SectRect(globalStrucRect, aGDScreenRect, gdSectRect)) { sectArea = IntMultiply(gdSectRect.Length(vSel), gdSectRect.Length(hSel)); if (sectArea > maxSectArea) // do we have a new winner? { maxSectArea = sectArea; maxSectGD = aGDHandle; } } aGDHandle = GetNextDevice(aGDHandle); } if (maxSectGD != GetMainDevice()) screenRect = (*maxSectGD)->gdRect; else { /* Account for menu bar on the main screen. Don't just assume that its at the top of the screen! */ #if qDebug UseTempRgn("TWindow.GetMaxIntersectedDevice"); #endif RectRgn(gTempRgn, (*maxSectGD)->gdRect);// main screen with menubar SectRgn(gTempRgn, GetGrayRgn(), gTempRgn);// GetGrayRgn == desktop rgn w/o menubar screenRect = (*gTempRgn)->rgnBBox; // => main screen w/o menubar #if qDebug DoneWithTempRgn(); #endif } return maxSectGD; } else { /* Account for menu bar on the main screen. Don't just assume that its at the top of the screen! */ #if qDebug UseTempRgn("TWindow.GetMaxIntersectedDevice"); #endif RectRgn(gTempRgn, qd.screenBits.bounds);// main screen with menubar SectRgn(gTempRgn, GetGrayRgn(), gTempRgn);// GetGrayRgn == desktop rgn w/o menubar screenRect = (*gTempRgn)->rgnBBox; // => main screen w/o menubar #if qDebug DoneWithTempRgn(); #endif return NULL; // we only have GDHandle in CQD world } } //-------------------------------------------------------------------------------------------------- #pragma segment MAInspector pascal void TWindow::GetInspectorName(Str255& inspectorName)// override { if ((fWMgrWindow) && (!(((long)fWMgrWindow) & 1)))// NOT ODD (fWMgrWindow) this->GetTitle(inspectorName); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal GrafPtr TWindow::GetGrafPort(void) // override { if (gPrinting || gDrawingPictScrap) return qd.thePort; //thePort assumed to be set by print handler else return ((GrafPtr)fWMgrWindow); // if it's NULL it's NULL } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal TEvtHandler* TWindow::GetTarget(void) { return fTarget; } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::GetTitle(Str255& theTitle) { if (fWMgrWindow) GetWTitle(fWMgrWindow, theTitle); else theTitle = ""; } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal TWindow* TWindow::GetWindow(void) // override { return this; } //-------------------------------------------------------------------------------------------------- #pragma segment MAClose pascal void TWindow::GoAwayByUser(const VPoint& theMouse) { VPoint globalVMouse(theMouse); this->LocalToSuper(globalVMouse); if (fIsClosable && TrackGoAway(fWMgrWindow, globalVMouse)) { Boolean oldObjectPerm; oldObjectPerm = AllocateObjectsFromPerm(FALSE);// Guarantee the allocation TCloseWindowCommand * aCloseWindowCommand = new TCloseWindowCommand; AllocateObjectsFromPerm(oldObjectPerm); aCloseWindowCommand->ICloseWindowCommand(cClose, this); this->PostCommand(aCloseWindowCommand); } } //-------------------------------------------------------------------------------------------------- #pragma segment MASelCommand pascal Boolean TWindow::HandleMouseDown(const VPoint& theMouse, TToolboxEvent* event, Point hysteresis)// override { Boolean dispatchByPartCode; short aPartCode; Boolean result; result = TRUE; // find out where the mouse was pressed aPartCode = this->GetPartCode(theMouse); /* note the following workaround special case for inactive windows that want the first click - GetPartCode will tell us that the mouse was pressed "inContent" so we should select the window, and then call GetPartCode again to find out where the mouse was *really* pressed */ dispatchByPartCode = TRUE; if ((gApplication->GetActiveWindow() != this) && (aPartCode == inContent)) { this->Select(); if (fDoFirstClick) { gApplication->UpdateAllWindows(); aPartCode = this->GetPartCode(theMouse);// now, where is the mouse } else dispatchByPartCode = FALSE; } // dispatch according to where the mouse was pressed if (dispatchByPartCode) switch (aPartCode) { case inContent: result = inherited::HandleMouseDown(theMouse, event, hysteresis); break; case inDrag: this->MoveByUser(theMouse); break; case inGrow: this->ResizeByUser(theMouse); break; case inGoAway: this->GoAwayByUser(theMouse); break; case inZoomIn: case inZoomOut: this->ZoomByUser(theMouse, aPartCode); break; case inDesk: break; } else result = FALSE; return result; } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean TWindow::HasPendingUpdate(void) { return !EmptyRgn(((WindowPeek)fWMgrWindow)->updateRgn); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal short TWindow::GetPartCode(const VPoint& theMouse)// override { WindowPtr aWMgrWindow; short partCode; VPoint globalVWhere(theMouse); this->LocalToSuper(globalVWhere); // Call FindWindow to determine the partcode partCode = FindWindow(globalVWhere, aWMgrWindow); if (aWMgrWindow != fWMgrWindow) // if we fail this sanity check, then { if (qDebug) ProgramBreak("in TWindow.GetPartCode: passed a VPoint that didn''t belong to the window"); return inDesk; // …we don't really know where it is! } else return partCode; /* passed the sanity check so return the part code we got back from FindWindow */ } //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen pascal void TWindow::InstallDocument(TDocument* itsDocument) { Str255 aString; fDocument = itsDocument; if (itsDocument) { gApplication->DeleteFreeWindow(this); // Just in case… itsDocument->AddWindow(this); itsDocument->GetTitle(aString); if (!aString.IsEmpty()) // not an untitled document this->SetTitleForDoc(aString); fNextHandler = itsDocument; } else { gApplication->AddFreeWindow(this); fNextHandler = gApplication; } } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal Boolean TWindow::IsDismissed(void) { return fDismissed; } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal void TWindow::Dismiss(void) { fDismissed = TRUE; } //-------------------------------------------------------------------------------------------------- pascal long PushLong(short h, short v) // This can be used to push a longint given a point. PushLong(aPt.h,aPt.v); = { 0x2E9F}; // MOVE.L (A7)+,(A7) //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal Boolean TWindow::IsDraggable(const Rect& whichRect) // Returns TRUE if any of the corner points of whichRect are draggable. { Handle wDefProc; short variant; SignedByte saveState; Boolean rgnsWereBuilt; Boolean result; result = TRUE; wDefProc = GetAndLoadWDefProc(((WindowPeek)fWMgrWindow)->windowDefProc); if (wDefProc) { saveState = LockHandleHigh(wDefProc); rgnsWereBuilt = this->BuildWindowRgns(kBuild);// regions needed for hit testing variant = GetWindowVariant(fWMgrWindow); if ((CallWDefProc(variant, fWMgrWindow, wHit, PushLong(whichRect.left, whichRect.top), wDefProc) != wInDrag) && (CallWDefProc(variant, fWMgrWindow, wHit, PushLong(whichRect.right, whichRect.bottom), wDefProc) != wInDrag) && (CallWDefProc(variant, fWMgrWindow, wHit, PushLong(whichRect.left, whichRect.bottom), wDefProc) != wInDrag) && (CallWDefProc(variant, fWMgrWindow, wHit, PushLong(whichRect.right, whichRect.top), wDefProc) != wInDrag)) result = FALSE; // …no, so window _isn't_ draggable HSetState(wDefProc, saveState); this->BuildWindowRgns(rgnsWereBuilt); } else { if (qDebug) ProgramBreak("###TWindow.IsDraggable: can't load wdef"); return FALSE; } return result; } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal Boolean TWindow::IsHiddenOnSuspend(void) { return fHideOnSuspend; /* clipboard windows && floaters should return TRUE (and any other window that wants to get hidden when the application is suspended by the Process Manager). */ } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean TWindow::IsShown(void) // override { if (fWMgrWindow) return ((WindowPeek)fWMgrWindow)->visible; else return FALSE; } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean TWindow::IsActive(void) // override { return fIsActive; } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::DoInvalidateRgn(RgnHandle badRgn) { if ((qd.thePort == fWMgrWindow) && this->IsShown()) if (!EmptyRgn(badRgn)) { InvalRgn(badRgn); if (gShowInvalidations) FillRgn(badRgn, qd.ltGray); if (fUpdating) // clip INCLUDES the update region UnionRgn(qd.thePort->clipRgn, badRgn, qd.thePort->clipRgn); else // clip EXCLUDES the update region DiffRgn(qd.thePort->clipRgn, badRgn, qd.thePort->clipRgn); } } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::DoValidateRgn(RgnHandle goodRgn) { if ((qd.thePort == fWMgrWindow) && this->IsShown()) if (!EmptyRgn(goodRgn)) { ValidRgn(goodRgn); if (fUpdating) // clip INCLUDES the update region UnionRgn(qd.thePort->clipRgn, goodRgn, qd.thePort->clipRgn); else // clip EXCLUDES the update region DiffRgn(qd.thePort->clipRgn, goodRgn, qd.thePort->clipRgn); } } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal Boolean TWindow::BuildWindowRgns(Boolean build) // Calculate window size including structure region (i.e. title bar). To do this // we need to force the window to compute its structure region by calling its defproc, // if the window isn't shown. If build is FALSE, set the regions back to empty regions, so as not // to confuse the window manager. Return the previous state of the regions. { WindowRecord & theWindowRecord = *((WindowPeek)fWMgrWindow); // The regions are considered to be built if either: // a) the window is shown; or // b) the structure rgn is not empty. if (this->IsShown() || !EmptyRgn(theWindowRecord.strucRgn)) { if ((build != kBuild) && !this->IsShown()) { SetEmptyRgn(theWindowRecord.strucRgn); SetEmptyRgn(theWindowRecord.contRgn); } return kBuild; } else { if (build == kBuild) { Handle wDefProc = GetAndLoadWDefProc(theWindowRecord.windowDefProc); if (wDefProc) { SignedByte saveState = LockHandleHigh(wDefProc); CallWDefProc(GetWindowVariant(fWMgrWindow), fWMgrWindow, wCalcRgns, 0, wDefProc); HSetState(wDefProc, saveState); // Calculate offset from top-left of window structure to top-left of window content fContRgnInset = (*theWindowRecord.contRgn)->rgnBBox[topLeft] - (*theWindowRecord.strucRgn)->rgnBBox[topLeft]; Rect globalStrucRect = (*theWindowRecord.strucRgn)->rgnBBox; Rect globalContRect = (*theWindowRecord.contRgn)->rgnBBox; fContDifference.v = (globalStrucRect.Length(vSel)) - (globalContRect.Length(vSel)); fContDifference.h = (globalStrucRect.Length(hSel)) - (globalContRect.Length(hSel)); } } return !kBuild; } } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::Locate(const VPoint& newLoc, Boolean invalidate) // override { if ((fWMgrWindow) && (newLoc != fLocation)) MoveWindow(fWMgrWindow, (short)newLoc.h, (short)newLoc.v, FALSE); // ??? should offset by fContRgnInset.v //!!! VCoordinate->short inherited::Locate(newLoc, invalidate); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::Select(void) { gApplication->SelectWMgrWindow(fWMgrWindow); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::MoveByUser(const VPoint& theMouse) { VPoint globalVMouse(theMouse); this->LocalToSuper(globalVMouse); DragWindow(fWMgrWindow, globalVMouse,fMoveBounds); // Don't forget to tell the window object Point currLoc(fWMgrWindow->portRect[topLeft]); LocalToGlobal(currLoc); // can't use localtosuper since flocation not updated yet this->Locate(currLoc, kDontInvalidate); } //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen pascal void TWindow::Open(void) // override { if (!this->IsShown()) { // Keep us matching the window since we are parallel structures // Be sure all views are sized right this->Resize(VPoint(fWMgrWindow->portRect.Length(vSel), fWMgrWindow->portRect.Length(hSel)), kDontInvalidate); this->AdjustSize(); // Give non-template views a shot at correcting for sizedeterminers if (fMustAdapt && !fAdapted) this->AdaptToScreen(); if ((fMustHorzCenter && !fHorzCentered) || (fMustVertCenter && !fVertCentered)) this->Center(fMustHorzCenter, fMustVertCenter, fIsModal); if (fMustStagger && !fStaggered) { /* If both staggering and forcing on screen are specified then we must ensure that the window is forced on screen FIRST so that the staggering will occur in a visible (and usable) location. BUT, after staggering we must STILL ensure that the window is forced on screen so, we reset the forced flag so that forcing will occur on schedule later. */ if (fMustForceOnScreen && !fForcedOnScreen) { this->ForceOnScreen(); fForcedOnScreen = FALSE; // Make sure we can be forced again } this->SimpleStagger(kStdStaggerAmount, kStdStaggerAmount, gStdStaggerCount); } if (fMustForceOnScreen && !fForcedOnScreen) this->ForceOnScreen(); // If fVisibleExtent is empty, UpdateCoordinates so our contents will be drawn if (fVisibleExtent.Empty()) this->UpdateCoordinates(); this->Show(TRUE, kRedraw); // Make me visible } inherited::Open(); // Tell subviews to open in case they care } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::PoseModally(void) { FailInfo fi; Boolean saveIsModal; VOLATILE(saveIsModal); // let the window "know" it's going to be placed a modal state saveIsModal = fIsModal; fIsModal = TRUE; gApplication->CommitLastCommand(); // Make sure that the undo menu reflects // the view being looked at. Otherwise // the undo menu will be wrong. this->Open(); this->Select(); // Bring it to the front fDismissed = FALSE; while (!this->IsDismissed()) { if (fi.Try()) { gApplication->PollEvent(kAllowApplicationToSleep); Success(fi); } else // Recover { if (fi.error != noErr) // If no error then keep the dialog running { this->Dismiss(); // Avoid validating selected edit text this->Close(); /* If an error then close the dialog and exit via failure mechanism */ fIsModal = saveIsModal; fi.ReSignal(); } } } fIsModal = saveIsModal; } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal void TWindow::RemovedASubView(TView* theSubView)// override { // Patch up the target chain. if (theSubView == fTarget) this->SetTarget(theSubView->fSuperView);//!!! Should we check fSuperView for NULL? else if (theSubView == gApplication->GetTarget()) gApplication->SetTarget(theSubView->fSuperView); } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal void TWindow::Resize(const VPoint& newSize, Boolean invalidate) // override { if (newSize != fSize) { SizeWindow(fWMgrWindow, (short)newSize.h, (short)newSize.v, invalidate);//!!! VCoordinate-> short VRect vr (-kSBarSizeMinus1, -kSBarSizeMinus1, 0, 0); // standard size of grow box // ??? any better way? // the grow box must be invalidated because it intrudes into the window content if (fIsResizable && invalidate) this->InvalidateVRect(vr + fSize); // old location inherited::Resize(newSize, invalidate); if (fIsResizable && invalidate) this->InvalidateVRect(vr + fSize); // old location } } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal void TWindow::ResizeByUser(const VPoint& theMouse) { if (fIsResizable) { VPoint globalVMouse(theMouse); this->LocalToSuper(globalVMouse); long growResult = GrowWindow(fWMgrWindow, globalVMouse, fResizeLimits); if (growResult) this->Resize(VPoint(HiWord(growResult),LoWord(growResult)), kInvalidate); } } //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen pascal void TWindow::SetResizeLimits(Point itsMinSize, Point itsMaxSize) { fResizeLimits = Rect(itsMinSize, itsMaxSize); // If the window is zoomable, keep the window's state data current if ((fProcID) & zoomDocProc) { Rect & theStdState = (*((WStateDataHandle)(((WindowPeek)fWMgrWindow)->dataHandle)))->stdState; theStdState.right = (short)Min(theStdState.right, fLocation.h + itsMaxSize.h - 1);//!!! long-> short theStdState.bottom = (short)Min(theStdState.bottom, fLocation.v + itsMaxSize.v - 1);//!!! long-> short } // If the window is not sized within the new limits, resize it to fit VPoint newSize = fSize; newSize.ConstrainTo(fResizeLimits); if (newSize != fSize) this->Resize(newSize, kDontInvalidate); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::SetTarget(TEvtHandler* newTarget)// override { long reason; TEvtHandler * currentTarget; if (!newTarget) // Would be annoying if a nil got in here! newTarget = this; /* If the window is active, the application's target is set, otherwise we simply save the new target in the window field */ currentTarget = gApplication->GetTarget(); if (newTarget != currentTarget) { if (this->IsActive()) // TRUE for floaters too! { reason = currentTarget->WillingToResignTarget(); if (reason == 0) { currentTarget->TargetValidationSucceeded(); currentTarget->ResignedWindowTarget(); gApplication->SetTarget(newTarget); fTarget = newTarget; newTarget->BecameWindowTarget(); } else currentTarget->TargetValidationFailed(reason); } else { fTarget->ResignedWindowTarget(); fTarget = newTarget; fTarget->BecameWindowTarget(); } } } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::SetTitle(const Str255& newTitle) { Str255 oldTitle; GetWTitle(fWMgrWindow, oldTitle); /* to minimize flash, we only set the title if it's different from the current title */ if (CompareStrings(oldTitle, newTitle) != sortsEqual) SetWTitle(fWMgrWindow, newTitle); } //-------------------------------------------------------------------------------------------------- #pragma segment MAFile pascal void TWindow::SetTitleForDoc(const Str255& newDocTitle) { Str255 title; if (fPreDocname > 0) // optimize for case of nothing to do { this->GetTitle(title); if (SubstituteInTitle(title, newDocTitle, fPreDocname, fConstTitle)) this->SetTitle(title); } } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal void TWindow::AboutToLoseControl(void) { Boolean oldManageActivation; if (this->IsShown() && this->IsHiddenOnSuspend()) { fWasHiddenOnSuspend = TRUE; oldManageActivation = fGenerateActivates; fGenerateActivates = FALSE; this->Show(FALSE, kRedraw); fGenerateActivates = oldManageActivation; } } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal void TWindow::RegainControl(void) { Boolean oldManageActivation; if (fWasHiddenOnSuspend) { fWasHiddenOnSuspend = FALSE; // !!! Any necessary activation is handled in TApplication.HandleSystemEvent oldManageActivation = fGenerateActivates; fGenerateActivates = FALSE; this->Show(TRUE, kRedraw); fGenerateActivates = oldManageActivation; } } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal void TWindow::Show(Boolean state, Boolean redraw) // override { if (state) this->Resize(VPoint(fWMgrWindow->portRect.Length(vSel), fWMgrWindow->portRect.Length(hSel)), redraw);// Be sure all views are sized right if (fGenerateActivates) { if (state) ShowWindow(fWMgrWindow); else HideWindow(fWMgrWindow); } else { ShowHide(fWMgrWindow, state); if (!state) this->Activate(FALSE); /* at least de-activate ourselves when hiding */ } // manage activation: if (fFloats) this->Activate(state); // for floaters, activation == visibility else if ((!state) && this->IsActive()) this->Activate(FALSE); // if active, de-activate ourselves when hiding inherited::Show(state, redraw); } //-------------------------------------------------------------------------------------------------- #pragma segment MAOpen pascal void TWindow::SimpleStagger(short dh, short dv, short& counter) { VRect theFrame; // The topLeft of the window must fall in here. short nSlots; short slot; fStaggered = TRUE; this->GetFrame(theFrame); theFrame[botRight] = (theFrame[topLeft] + VPoint(fMoveBounds[botRight])) - theFrame[botRight]; /* This covers the case of dh && dv both >= 0; if either is less than 0, the right (bottom) limit is set to the left (top) edge of the screen -- allowing for some margin. This makes the right (bottom) edge less than the left (top) edge, but this is OK since the / statement below will be dividing 2 negative numbers. */ if (dh < 0) theFrame.right = fMoveBounds.left; if (dv < 0) theFrame.bottom = fMoveBounds.top; // This code avoids divide by zero problems if (!dh || !dv) nSlots = 0; else nSlots = (short)Min((theFrame.Length(hSel) + dh - 1) / dh, (theFrame.Length(vSel) + dv - 1) / dv);//!!! long-> short if (!nSlots) slot = 0; else slot = counter % nSlots; if (slot) // move the window { // The place to position the window this->Locate(theFrame[topLeft] + VPoint((slot * dv), (slot * dh)), kDontInvalidate); } ++counter; } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal void TWindow::Update(void) // override { if (this->HasPendingUpdate()) { fUpdating = TRUE; // So TWindow.Focus will know to focus TO the update rgn this->InvalidateFocus(); // this->InvalidateRgn(((WindowPeek)fWMgrWindow)->updateRgn); // CopyRgn(((WindowPeek)fWMgrWindow)->updateRgn, gTempRgn2); // this->SuperToLocalRgn(gTempRgn2); // this->InvalidateRgn(gTempRgn2); FailInfo fi; if (fi.Try()) { if (gShowInvalidations && this->Focus()) FillRgn(((WindowPeek)fWMgrWindow)->updateRgn, qd.ltGray); this->DrawContents(); fi.Success(); } else // Recover { SetEmptyRgn(((WindowPeek)fWMgrWindow)->updateRgn); // Or we get into an infinite loop // trying to update the window when // displaying an alert fUpdating = FALSE; this->InvalidateFocus(); fi.ReSignal(); } fUpdating = FALSE; // attempt to preserve the focus else blow it off // if (this->IsFocused()) // { // VRect theExtent; // this->GetExtent(theExtent); // this->ValidateVRect(theExtent); // } // else { SetEmptyRgn(((WindowPeek)fWMgrWindow)->updateRgn); this->InvalidateFocus(); } } } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes //!!! Former nested routine, now a private method pascal void TWindow::GetStandardStateFrame(const VRect& boundingRect, VRect& stdFrame) { const short edge = 2; // leave space around window structure area, settable? VPoint delta; VRect localBoundingRect = boundingRect; localBoundingRect.Inset(VPoint(edge, edge)); // calculate the maximum structure size delta.h = Min((localBoundingRect.Length(hSel)), fResizeLimits[botRight][hSel] + fContDifference[hSel]);//!!! long-> short delta.v = Min((localBoundingRect.Length(vSel)), fResizeLimits[botRight][vSel] + fContDifference[vSel]);//!!! long-> short // Relocate the view only if necessary if ((fLocation.v >= localBoundingRect.top) && ((fLocation.v + delta.v - fContDifference.v - 1) <= localBoundingRect.bottom)) stdFrame.top = fLocation.v; else // center in the screen stdFrame.top = localBoundingRect.top + fContRgnInset.v + ((localBoundingRect.Length(vSel)) - delta.v) / 2; if ((fLocation.h >= localBoundingRect.left) && ((fLocation.h + delta.h - fContDifference.h - 1) <= localBoundingRect.right)) stdFrame.left = fLocation.h; else // center in the screen stdFrame.left = localBoundingRect.left + fContRgnInset.h + ((localBoundingRect.Length(hSel)) - delta.h) / 2; stdFrame[botRight] = stdFrame[topLeft] + delta - VPoint(fContDifference) - VPoint(1, 1); } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes //!!! Former nested routine, now a private method pascal void TWindow::GetUserStateFrame(const VRect& /* boundingRect */, VRect& userFrame) { if ((fProcID) & zoomDocProc) // check for a zoomable defproc userFrame = (*((WStateDataHandle)(((WindowPeek)fWMgrWindow)->dataHandle)))->userState; else if (qDebug) ProgramBreak("Whoops"); } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal void TWindow::Zoom(short partCode) { Rect aGDScreenRect; VRect vr; // Find out where the window would like to be zoomed out to this->GetMaxIntersectedDevice(aGDScreenRect); VRect aGDScreenVRect(aGDScreenRect); if (partCode == inZoomOut) { // new zoom-out rect GetStandardStateFrame(aGDScreenVRect, vr); if ((fProcID) & zoomDocProc) // check for a zoomable defproc (*((WStateDataHandle)(((WindowPeek)fWMgrWindow)->dataHandle)))->stdState = vr; } else { // new zoom-in rect GetUserStateFrame(aGDScreenVRect, vr); if ((fProcID) & zoomDocProc) // check for a zoomable defproc (*((WStateDataHandle)(((WindowPeek)fWMgrWindow)->dataHandle)))->userState = vr; } if (this->Focus()) // The ROM requires that thePort be the window being zoomed. { Rect oldPortRect = qd.thePort->portRect; if (vr[topLeft] != fLocation) // it moved EraseRect(oldPortRect); if ((fProcID) & zoomDocProc) // check for a zoomable defproc ZoomWindow(fWMgrWindow, partCode, FALSE); // let the View know what we've done if (vr[topLeft] == fLocation) // it didn't move: MacApp will handle invalidating, thank you this->ValidateRect(oldPortRect); else this->Locate(vr[topLeft], kDontInvalidate); this->Resize(VPoint(fWMgrWindow->portRect.Length(vSel), fWMgrWindow->portRect.Length(hSel)), kInvalidate); } } //-------------------------------------------------------------------------------------------------- #pragma segment MANonRes pascal void TWindow::ZoomByUser(const VPoint& theMouse, short partCode) { VPoint globalVMouse(theMouse); this->LocalToSuper(globalVMouse); if (TrackBox(fWMgrWindow, globalVMouse, partCode)) this->Zoom(partCode); } //-------------------------------------------------------------------------------------------------- #pragma segment MAFields pascal void TWindow::Fields(TObject* obj) // override { obj->DoToField("TWindow", NULL, bClass); obj->DoToField("fWMgrWindow", &fWMgrWindow, bWindowPtr); obj->DoToField("fProcID", &fProcID, bInteger); obj->DoToField("fMoveBounds", &fMoveBounds, bRect); obj->DoToField("fResizeLimits", &fResizeLimits, bRect); obj->DoToField("fTarget", &fTarget, bObject); obj->DoToField("fTargetID", &fTargetID, bIDType); obj->DoToField("fPreDocName", &fPreDocname, bInteger); obj->DoToField("fConstTitle", &fConstTitle, bInteger); obj->DoToField("fMustAdapt", &fMustAdapt, bBoolean); obj->DoToField("fMustHorzCenter", &fMustHorzCenter, bBoolean); obj->DoToField("fMustVertCenter", &fMustVertCenter, bBoolean); obj->DoToField("fMustStagger", &fMustStagger, bBoolean); obj->DoToField("fMustForceOnScreen", &fMustForceOnScreen, bBoolean); obj->DoToField("fAdapted", &fAdapted, bBoolean); obj->DoToField("fHorzCentered", &fHorzCentered, bBoolean); obj->DoToField("fVertCentered", &fVertCentered, bBoolean); obj->DoToField("fStaggered", &fStaggered, bBoolean); obj->DoToField("fForcedOnScreen", &fForcedOnScreen, bBoolean); obj->DoToField("fIsActive", &fIsActive, bBoolean); obj->DoToField("fIsResizable", &fIsResizable, bBoolean); obj->DoToField("fIsClosable", &fIsClosable, bBoolean); obj->DoToField("fFreeOnClosing", &fFreeOnClosing, bBoolean); obj->DoToField("fDisposeOnFree", &fDisposeOnFree, bBoolean); obj->DoToField("fClosesDocument", &fClosesDocument, bBoolean); obj->DoToField("fOpenInitially", &fOpenInitially, bBoolean); obj->DoToField("fIsModal", &fIsModal, bBoolean); obj->DoToField("fDoFirstClick", &fDoFirstClick, bBoolean); obj->DoToField("fFloats", &fFloats, bBoolean); obj->DoToField("fDismissed", &fDismissed, bBoolean); obj->DoToField("fHideOnSuspend", &fHideOnSuspend, bBoolean); obj->DoToField("fWasHiddenOnSuspend", &fWasHiddenOnSuspend, bBoolean); obj->DoToField("fContRgnInset", &fContRgnInset, bPoint); obj->DoToField("fContDifference", &fContDifference, bPoint); obj->DoToField("fGenerateActivates", &fGenerateActivates, bBoolean); inherited::Fields(obj); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes Boolean IsDocumentWindow(WindowPtr aWindow) // if a window is not a floater window and is not a system window then it is a document window { return ((!IsFloatWindow(aWindow)) && (!(((WindowPeek)(aWindow))->windowKind < 0))); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean IsDialog(WindowPtr window) { return ((((WindowPeek)window)->windowKind == dialogKind) && (GetWindowVariant(window) == dBoxProc)); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean IsGhostWindow(WindowPtr window) { return (window == (WindowPtr)(*((LongIntPtr)GhostWindow))); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes pascal Boolean IsFloatWindow(WindowPtr window) { return (((WindowPeek)window)->windowKind == kFloatWindowKind); } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes // returns the last floating window in the window list pascal WindowPtr GetLastFloatingWindowPtr(void) { CWMgrIterator iter; WindowPtr lastFloatWindowPtr = NULL; for (WindowPtr aWindowPtr = iter.FirstWMgrWindow(); iter.More(); aWindowPtr = iter.NextWMgrWindow()) { if (IsFloatWindow(aWindowPtr)) lastFloatWindowPtr = aWindowPtr; else if (!(((WindowPeek)aWindowPtr)->windowKind < 0)) break; } return lastFloatWindowPtr; } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes // returns the first hilited, visible, non-system document window in the window list. // Ignores the ghost window (if any). pascal WindowPtr MAGetActiveWindow(void) { CWMgrIterator iter; for (WindowPtr aWindowPtr = iter.FirstWMgrWindow(); iter.More(); aWindowPtr = iter.NextWMgrWindow()) if ((((WindowPeek)aWindowPtr)->hilited) && (((WindowPeek)aWindowPtr)->visible) && IsDocumentWindow(aWindowPtr) && !IsGhostWindow(aWindowPtr)) return aWindowPtr; return NULL; } //-------------------------------------------------------------------------------------------------- #pragma segment MAWindowRes // Returns the first visible, non-floater window in the window list. Ignores the ghost window (if any). pascal WindowPtr MAFrontWindow(void) { CWMgrIterator iter; for (WindowPtr aWindowPtr = iter.FirstWMgrWindow(); iter.More(); aWindowPtr = iter.NextWMgrWindow()) if ((((WindowPeek)aWindowPtr)->visible) && !IsFloatWindow(aWindowPtr) && !IsGhostWindow(aWindowPtr)) return aWindowPtr; return NULL; }